--编写者：alt
--功能介绍：创建世界共用空间的箱子
--例如
local playername = "herta"
local containerid = "herta_hat"
local containerprefab = "herta_hat_container"
local containerproxyname = "herta_hat_container_proxy"
local chestprefab = nil       --这个需要自己写个prefab
local magicaltoolprefab = nil --这个需要自己写个prefab
--资源需要自己加载
do
    local POCKETDIMENSIONCONTAINER_DEFS = require("prefabs/pocketdimensioncontainer_defs").POCKETDIMENSIONCONTAINER_DEFS
    table.insert(POCKETDIMENSIONCONTAINER_DEFS, {
        name = containerid,
        prefab = containerprefab,
        ui = "anim/ui_portal_shadow_3x4.zip",
        widgetname = containerprefab,
    })
end
do
    local registerlist = {}
    local oldLoadPrefabFile = GLOBAL.LoadPrefabFile
    function GLOBAL.LoadPrefabFile(filename, async_batch_validation, search_asset_first_path, ...)
        if registerlist[filename] then
            assert(not async_batch_validation or not search_asset_first_path,
                "search_asset_first_path and async_batch_validation cannot both be defined")
            local fn = registerlist[filename]
            assert(fn, "Could not load file ")
            assert(type(fn) == "function", "Prefab file doesn't return a callable chunk: " .. filename)
            setfenv(fn, GLOBAL)
            local ret = { fn() }
            if ret then
                for i, val in ipairs(ret) do
                    if type(val) == "table" and val.is_a and val:is_a(GLOBAL.Prefab) then
                        val.search_asset_first_path = search_asset_first_path
                        if async_batch_validation then
                            RegisterPrefabsImpl(val, function(prefab, asset)
                                TheSim:AddBatchVerifyFileExists(asset.file)
                            end)
                        else
                            RegisterSinglePrefab(val)
                        end
                        GLOBAL.PREFABDEFINITIONS[val.name] = val
                    end
                end
            end

            return ret
        end
        return oldLoadPrefabFile(filename, async_batch_validation, search_asset_first_path, ...)
    end

    local MOD_util = {}
    function MOD_util:RegisterModPrefab(prefab_path, prefabfn)
        registerlist["prefabs/" .. prefab_path] = prefabfn
        table.insert(PrefabFiles, prefab_path)
    end

    local function prefabfn()
        local function fn()
            local inst = CreateEntity()

            inst.entity:AddNetwork()

            inst:AddTag("CLASSIFIED")
            inst:Hide()

            inst:AddComponent("container_proxy")

            inst.entity:SetPristine()

            if not TheWorld.ismastersim then
                return inst
            end

            inst.components.container_proxy:SetMaster(TheWorld:GetPocketDimensionContainer(containerid))

            inst.persists = false

            return inst
        end
        return Prefab(containerproxyname, fn)
    end

    MOD_util:RegisterModPrefab(containerproxyname, prefabfn)
end


do
    local function AttachShadowContainer(inst)
        inst.components.container_proxy:SetMaster(TheWorld:GetPocketDimensionContainer(containerid))
    end
    AddPrefabPostInit(chestprefab, function(inst)
        if not TheWorld.ismastersim then
            return inst
        end
        local old = inst.OnLoadPostPass
        inst.OnLoadPostPass = function(self, ...)
            AttachShadowContainer(self)
            if old then
                old(self, ...)
            end
        end
        if not POPULATING then
            AttachShadowContainer(inst)
        end
    end)
end
do
    local function top_onclose(tophatcontainer)
        tophatcontainer.tophat.components.magiciantool:StopUsing()
    end
    local function top_onstartusing(inst, doer)
        if inst.container == nil then
            inst.container = SpawnPrefab(containerproxyname)
            inst.container.Network:SetClassifiedTarget(doer)
            inst.container.tophat = inst
            inst.container.components.container_proxy:SetOnCloseFn(top_onclose)
        end
        doer:PushEvent("opencontainer", { container = inst.container.components.container_proxy:GetMaster() })
        inst.container.components.container_proxy:Open(doer)
        if doer.SoundEmitter ~= nil and not doer.SoundEmitter:PlayingSound("magician_tophat_loop") then
            doer.SoundEmitter:PlaySound("maxwell_rework/shadow_magic/storage_void_LP", "magician_tophat_loop")
        end
    end
    local function top_onstopusing(inst, doer)
        if inst.container ~= nil then
            inst.container.components.container_proxy:Close(doer)
            doer:PushEvent("closecontainer", { container = inst.container.components.container_proxy:GetMaster() })
            inst.container:Remove()
            inst.container = nil
        end
        if doer.SoundEmitter ~= nil then
            doer.SoundEmitter:KillSound("magician_tophat_loop")
        end
    end
    if magicaltoolprefab then
        AddPrefabPostInit(magicaltoolprefab, function(inst)
            if not TheWorld.ismastersim then
                return inst
            end
            inst:AddComponent("magiciantool")
            inst.components.magiciantool:SetOnStartUsingFn(top_onstartusing)
            inst.components.magiciantool:SetOnStopUsingFn(top_onstopusing)
        end)
        if playername then
            do
                --注意一下克雷的bug
                --要和老麦一样在onload里面写上
                AddPrefabPostInit(playername, function(inst)
                    if not TheWorld.ismastersim then
                        return inst
                    end
                    local old = inst.OnLoad
                    inst.OnLoad = function(...)
                        old(...)
                        if inst.components.magician then
                            inst.components.magician:StopUsing()
                        end
                    end
                end)
            end
        end
    end
end
